package maple.thelittleredbook.content.service;

import lombok.extern.slf4j.Slf4j;
import maple.thelittleredbook.content.entity.Image;
import maple.thelittleredbook.content.entity.Video;
import maple.thelittleredbook.content.mapper.ImageMapper;
import maple.thelittleredbook.content.mapper.VideoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import maple.thelittleredbook.content.entity.Content;
import maple.thelittleredbook.content.entity.ContentOperationLog;
import maple.thelittleredbook.content.mapper.ContentMapper;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.List;
import java.util.UUID;

/**
 * 异步文件上传服务 - 重构版本
 * 集成操作日志跟踪功能
 */
@Slf4j
@Service
public class AsyncFileService {

    private final ContentMapper contentMapper;
    private final VideoMapper videoMapper;
    private final ImageMapper imageMapper;
    private final ContentOperationLogService operationLogService;

    @Value("${file.server.url}")
    private String fileServerUrl;

    @Value("${file.server.auth.username}")
    private String fileServerUsername;

    @Value("${file.server.auth.password}")
    private String fileServerPassword;

    @Value("${file.cover.default-path}")
    private String defaultCoverPath;

    @Autowired
    public AsyncFileService(ContentMapper contentMapper, VideoMapper videoMapper, ImageMapper imageMapper,
                            ContentOperationLogService operationLogService) {
        this.contentMapper = contentMapper;
        this.videoMapper = videoMapper;
        this.imageMapper = imageMapper;
        this.operationLogService = operationLogService;
    }

    /**
     * 异步上传默认封面
     */
    @Async
    public void uploadDefaultCoverAsync(Long contentId, Long operationLogId) {
        try {
            log.info("开始异步上传默认封面，内容ID: {}, 操作日志ID: {}", contentId, operationLogId);
            copyDefaultCoverToServer(contentId);
            log.info("默认封面上传成功，内容ID: {}", contentId);

            // 更新操作日志进度
            operationLogService.incrementCompletedOperations(operationLogId);

            // 检查是否所有操作都完成，如果是则更新内容状态
            checkAndUpdateContentStatus(contentId, operationLogId);

        } catch (Exception e) {
            log.error("默认封面上传失败，内容ID: {}", contentId, e);
            operationLogService.markOperationFailed(operationLogId, "默认封面上传失败: " + e.getMessage());
            updateContentUploadStatus(contentId, "FAILED");
        }
    }

    /**
     * 异步上传用户自定义封面（从临时文件）
     */
    @Async
    public void uploadCoverFromTempAsync(Long contentId, String tempFilePath, Long operationLogId) {
        try {
            log.info("开始异步上传用户自定义封面，内容ID: {}, 临时文件: {}, 操作日志ID: {}",
                    contentId, tempFilePath, operationLogId);

            String filePath = "springboot/littleRedBook/content/" + contentId + "/cover.jpg";
            uploadFileFromTemp(tempFilePath, filePath, getImageContentType(tempFilePath));
            log.info("用户自定义封面上传成功，内容ID: {}", contentId);

            // 更新操作日志进度
            operationLogService.incrementCompletedOperations(operationLogId);

            // 检查是否所有操作都完成
            checkAndUpdateContentStatus(contentId, operationLogId);

        } catch (Exception e) {
            log.error("用户自定义封面上传失败，内容ID: {}", contentId, e);
            operationLogService.markOperationFailed(operationLogId, "用户封面上传失败: " + e.getMessage());
            updateContentUploadStatus(contentId, "FAILED");
        } finally {
            deleteTempFile(tempFilePath);
        }
    }

    /**
     * 异步上传图片（从临时文件）
     */
    @Async
    public void uploadImagesFromTempAsync(Long contentId, List<String> tempImagePaths,
                                          List<String> imageIds, Long operationLogId) {
        try {
            log.info("开始异步上传图片，内容ID: {}, 图片数量: {}, 操作日志ID: {}",
                    contentId, tempImagePaths.size(), operationLogId);

            for (int i = 0; i < tempImagePaths.size() && i < imageIds.size(); i++) {
                String imageId = imageIds.get(i);
                String tempPath = tempImagePaths.get(i);

                try {
                    String extension = getFileExtension(tempPath);
                    String fileName = imageId + extension;
                    String filePath = "springboot/littleRedBook/content/" + contentId + "/images/" + fileName;

                    uploadFileFromTemp(tempPath, filePath, getImageContentType(tempPath));
                    log.info("图片上传成功，内容ID: {}, 图片ID: {}, 文件名: {}", contentId, imageId, fileName);

                    // 每上传成功一张图片就更新进度
                    operationLogService.incrementCompletedOperations(operationLogId);

                } catch (Exception e) {
                    log.error("单个图片上传失败，内容ID: {}, 图片ID: {}", contentId, imageId, e);
                    operationLogService.markOperationFailed(operationLogId,
                            "图片 " + imageId + " 上传失败: " + e.getMessage());
                    updateContentUploadStatus(contentId, "FAILED");
                    return; // 任何一张图片失败就停止后续上传
                } finally {
                    deleteTempFile(tempPath);
                }
            }

            log.info("所有图片上传完成，内容ID: {}", contentId);

            // 检查是否所有操作都完成
            checkAndUpdateContentStatus(contentId, operationLogId);

        } catch (Exception e) {
            log.error("图片批量上传异常，内容ID: {}", contentId, e);
            tempImagePaths.forEach(this::deleteTempFile);
            operationLogService.markOperationFailed(operationLogId, "图片批量上传异常: " + e.getMessage());
            updateContentUploadStatus(contentId, "FAILED");
        }
    }

    /**
     * 异步上传视频（从临时文件）
     */
    @Async
    public void uploadVideoFromTempAsync(Long contentId, String tempFilePath,
                                         String videoId, Long operationLogId) {
        try {
            log.info("开始异步上传视频，内容ID: {}, 临时文件: {}, 操作日志ID: {}",
                    contentId, tempFilePath, operationLogId);

            String extension = getFileExtension(tempFilePath);
            String fileName = videoId + extension;
            String filePath = "springboot/littleRedBook/content/" + contentId + "/video/" + fileName;

            uploadFileFromTemp(tempFilePath, filePath, getVideoContentType(tempFilePath));
            log.info("视频上传成功，内容ID: {}, 视频ID: {}, 文件名: {}", contentId, videoId, fileName);

            // 更新操作日志进度
            operationLogService.incrementCompletedOperations(operationLogId);

            // 检查是否所有操作都完成
            checkAndUpdateContentStatus(contentId, operationLogId);

        } catch (Exception e) {
            log.error("视频上传失败，内容ID: {}", contentId, e);
            operationLogService.markOperationFailed(operationLogId, "视频上传失败: " + e.getMessage());
            updateContentUploadStatus(contentId, "FAILED");
        } finally {
            deleteTempFile(tempFilePath);
        }
    }

    /**
     * 检查并更新内容状态
     * 只有当操作日志显示所有操作完成时，才将内容状态设为COMPLETED
     */
    private void checkAndUpdateContentStatus(Long contentId, Long operationLogId) {
        ContentOperationLog Oplog = operationLogService.getOperationLog(operationLogId);
        if (log != null && ContentOperationLog.STATUS_COMPLETED.equals(Oplog.getOperationStatus())) {
            // 检查该内容是否还有其他进行中的操作
            if (!operationLogService.hasProcessingOperations(contentId)) {
                updateContentUploadStatus(contentId, "COMPLETED");
                log.info("所有文件操作完成，内容状态更新为COMPLETED，内容ID: {}", contentId);
            }
        }
    }

    /**
     * 异步更新封面
     */
    @Async
    public void updateCoverAsync(Long contentId, String tempFilePath, Long operationLogId) {
        try {
            log.info("开始异步更新封面，内容ID: {}, 临时文件: {}, 操作日志ID: {}",
                    contentId, tempFilePath, operationLogId);

            // 1. 上传新封面文件
            String newCoverPath = "springboot/littleRedBook/content/" + contentId + "/cover.jpg";
            uploadFileFromTemp(tempFilePath, newCoverPath, getImageContentType(tempFilePath));
            log.info("新封面上传成功，内容ID: {}", contentId);

            // 2. 删除旧封面文件（如果不是默认封面）
            // 注意：这里我们总是覆盖cover.jpg，所以不需要删除旧文件
            // 如果以后需要保留历史版本，可以在这里添加删除逻辑

            // 3. 更新数据库中的封面URL（虽然URL路径没变，但可以更新时间戳等）
            updateContentCoverUrl(contentId);

            // 4. 更新操作日志进度
            operationLogService.incrementCompletedOperations(operationLogId);

            // 5. 检查并更新内容状态
            checkAndUpdateContentStatus(contentId, operationLogId);

            log.info("封面更新完成，内容ID: {}", contentId);

        } catch (Exception e) {
            log.error("封面更新失败，内容ID: {}", contentId, e);
            operationLogService.markOperationFailed(operationLogId, "封面更新失败: " + e.getMessage());
            updateContentUploadStatus(contentId, "FAILED");
        } finally {
            deleteTempFile(tempFilePath);
        }
    }

    /**
     * 更新内容表中的封面URL
     */
    private void updateContentCoverUrl(Long contentId) {
        Content content = contentMapper.selectById(contentId);
        if (content != null) {
            // 封面URL保持不变，但可以触发updated_at字段更新
            String coverUrl = fileServerUrl + "/files-get/springboot/littleRedBook/content/" + contentId + "/cover.jpg";
            content.setCoverUrl(coverUrl);
            contentMapper.updateById(content);
            log.info("内容封面URL已更新，内容ID: {}", contentId);
        }
    }

    /**
     * 异步更新视频
     */
    @Async
    public void updateVideoAsync(Long contentId, String tempFilePath, Long operationLogId) {
        try {
            log.info("开始异步更新视频，内容ID: {}, 临时文件: {}, 操作日志ID: {}",
                    contentId, tempFilePath, operationLogId);

            // 1. 查询旧视频记录
            List<Video> oldVideos = videoMapper.selectByContentId(contentId);
            if (oldVideos.isEmpty()) {
                throw new RuntimeException("未找到旧视频记录");
            }
            Video oldVideo = oldVideos.get(0); // 视频内容只有一个视频

            // 2. 生成新的视频ID和路径
            String newVideoId = UUID.randomUUID().toString();
            String extension = getFileExtension(tempFilePath);
            String newVideoPath = "springboot/littleRedBook/content/" + contentId + "/video/" + newVideoId + extension;

            // 3. 上传新视频文件
            uploadFileFromTemp(tempFilePath, newVideoPath, getVideoContentType(tempFilePath));
            log.info("新视频上传成功，内容ID: {}, 新视频ID: {}", contentId, newVideoId);

            // 4. 删除旧视频文件
            String oldVideoPath = extractFilePathFromUrl(oldVideo.getVideoUrl());
            if (oldVideoPath != null) {
                try {
                    deleteFileFromServer(oldVideoPath);
                    log.info("旧视频文件删除成功，内容ID: {}, 路径: {}", contentId, oldVideoPath);
                } catch (IOException e) {
                    log.warn("删除旧视频文件失败，内容ID: {}, 路径: {}, 错误: {}",
                            contentId, oldVideoPath, e.getMessage());
                    // 删除旧文件失败不影响整体流程
                }
            }

            // 5. 更新数据库记录
            updateVideoRecord(contentId, newVideoId, extension, oldVideo.getId());

            // 6. 更新操作日志进度
            operationLogService.incrementCompletedOperations(operationLogId);

            // 7. 检查并更新内容状态
            checkAndUpdateContentStatus(contentId, operationLogId);

            log.info("视频更新完成，内容ID: {}", contentId);

        } catch (Exception e) {
            log.error("视频更新失败，内容ID: {}", contentId, e);
            operationLogService.markOperationFailed(operationLogId, "视频更新失败: " + e.getMessage());
            updateContentUploadStatus(contentId, "FAILED");
        } finally {
            deleteTempFile(tempFilePath);
        }
    }

    /**
     * 更新视频记录
     */
    private void updateVideoRecord(Long contentId, String newVideoId, String extension, Long oldVideoRecordId) {
        try {
            // 构建新的视频URL
            String newVideoUrl = fileServerUrl + "/files-get/springboot/littleRedBook/content/"
                    + contentId + "/video/" + newVideoId + extension;

            // 更新现有记录而不是删除重建
            Video updateVideo = new Video();
            updateVideo.setId(oldVideoRecordId);
            updateVideo.setVideoUrl(newVideoUrl);

            int updated = videoMapper.updateById(updateVideo);
            if (updated > 0) {
                log.info("视频记录更新成功，内容ID: {}, 新URL: {}", contentId, newVideoUrl);
            } else {
                throw new RuntimeException("视频记录更新失败");
            }

        } catch (Exception e) {
            log.error("更新视频记录失败，内容ID: {}", contentId, e);
            throw new RuntimeException("更新视频记录失败: " + e.getMessage());
        }
    }

    /**
     * 从URL中提取文件路径
     */
    private String extractFilePathFromUrl(String fileUrl) {
        if (fileUrl == null) {
            return null;
        }


        // 需要提取: springboot/littleRedBook/content/19/video/uuid.mp4
        String prefix = "/files-get/";
        int index = fileUrl.indexOf(prefix);
        if (index >= 0) {
            return fileUrl.substring(index + prefix.length());
        }

        return null;
    }

    /**
     * 异步批量更新图片 - 使用临时文件路径
     */
    @Async
    public void updateImagesWithTempFilesAsync(Long contentId, List<Long> deleteImageIds,
                                               List<String> tempImagePaths, List<String> newImageIds,
                                               Long operationLogId) {
        try {
            log.info("开始异步批量更新图片，内容ID: {}, 操作日志ID: {}, 删除数: {}, 新增数: {}",
                    contentId, operationLogId,
                    deleteImageIds != null ? deleteImageIds.size() : 0,
                    tempImagePaths.size());

            boolean hasError = false;
            StringBuilder errorMessages = new StringBuilder();

            // 1. 处理图片删除操作
            if (deleteImageIds != null && !deleteImageIds.isEmpty()) {
                for (Long imageId : deleteImageIds) {
                    try {
                        processImageDeletion(contentId, imageId, operationLogId);
                        log.info("图片删除成功，内容ID: {}, 图片ID: {}", contentId, imageId);
                    } catch (Exception e) {
                        log.error("删除图片失败，内容ID: {}, 图片ID: {}", contentId, imageId, e);
                        hasError = true;
                        errorMessages.append("删除图片 ").append(imageId).append(" 失败: ").append(e.getMessage()).append("; ");
                        operationLogService.markOperationFailed(operationLogId, errorMessages.toString());
                        updateContentUploadStatus(contentId, "FAILED");
                        cleanupTempFiles(tempImagePaths);
                        return;
                    }
                }
            }

            // 2. 处理新图片上传操作（参考创建时的逻辑）
            if (!tempImagePaths.isEmpty() && !newImageIds.isEmpty()) {
                for (int i = 0; i < tempImagePaths.size() && i < newImageIds.size(); i++) {
                    String tempPath = tempImagePaths.get(i);
                    String imageId = newImageIds.get(i);

                    try {
                        processImageUploadFromTempFile(contentId, tempPath, imageId, operationLogId);
                        log.info("第{}张图片上传成功，内容ID: {}, 图片ID: {}", (i + 1), contentId, imageId);
                    } catch (Exception e) {
                        log.error("第{}张图片上传失败，内容ID: {}, 图片ID: {}", (i + 1), contentId, imageId, e);
                        hasError = true;
                        errorMessages.append("上传第").append(i + 1).append("张图片失败: ").append(e.getMessage()).append("; ");
                        operationLogService.markOperationFailed(operationLogId, errorMessages.toString());
                        updateContentUploadStatus(contentId, "FAILED");
                        cleanupTempFiles(tempImagePaths);
                        return;
                    } finally {
                        // 处理完每个文件后立即删除临时文件
                        deleteTempFile(tempPath);
                    }
                }
                log.info("图片上传处理完成，内容ID: {}, 成功上传: {}张", contentId, tempImagePaths.size());
            }

            // 3. 检查操作是否全部完成
            if (!hasError) {
                checkAndUpdateContentStatus(contentId, operationLogId);
                log.info("图片批量更新完成，内容ID: {}", contentId);
            }

        } catch (Exception e) {
            log.error("图片批量更新异常，内容ID: {}", contentId, e);
            operationLogService.markOperationFailed(operationLogId, "图片批量更新异常: " + e.getMessage());
            updateContentUploadStatus(contentId, "FAILED");
            cleanupTempFiles(tempImagePaths);
        }
    }

// 3. 添加处理单个图片删除的方法
    /**
     * 处理单个图片删除操作
     */
    private void processImageDeletion(Long contentId, Long imageId, Long operationLogId) throws Exception {
        log.info("开始删除图片，内容ID: {}, 图片ID: {}", contentId, imageId);

        // 1. 查询图片记录
        Image image = imageMapper.selectByImageId(imageId);
        if (image == null) {
            throw new RuntimeException("图片记录不存在，ID: " + imageId);
        }

        // 2. 删除文件服务器上的文件
        String filePath = extractFilePathFromUrl(image.getImageUrl());
        if (filePath != null) {
            try {
                deleteFileFromServer(filePath);
                log.info("图片文件删除成功，内容ID: {}, 图片ID: {}, 路径: {}", contentId, imageId, filePath);
            } catch (IOException e) {
                log.warn("删除图片文件失败，内容ID: {}, 图片ID: {}, 路径: {}, 错误: {}",
                        contentId, imageId, filePath, e.getMessage());
                // 文件删除失败不影响数据库删除
            }
        }

        // 3. 删除数据库记录
        imageMapper.deleteById(imageId);
        log.info("图片记录删除成功，内容ID: {}, 图片ID: {}", contentId, imageId);

        // 4. 更新操作日志进度
        operationLogService.incrementCompletedOperations(operationLogId);
    }

// 4. 添加从临时文件处理图片上传的方法
    /**
     * 从临时文件处理图片上传（参考创建时的逻辑）
     */
    private void processImageUploadFromTempFile(Long contentId, String tempFilePath, String imageId, Long operationLogId) throws Exception {
        log.info("开始从临时文件上传图片，内容ID: {}, 图片ID: {}, 临时文件: {}", contentId, imageId, tempFilePath);

        // 1. 构建文件路径
        String extension = getFileExtension(tempFilePath);
        String fileName = imageId + extension;
        String filePath = "springboot/littleRedBook/content/" + contentId + "/images/" + fileName;

        // 2. 上传文件到服务器
        uploadFileFromTemp(tempFilePath, filePath, getImageContentType(tempFilePath));
        log.info("图片文件上传成功，内容ID: {}, 图片ID: {}", contentId, imageId);

        // 3. 创建数据库记录
        String imageUrl = fileServerUrl + "/files-get/" + filePath;
        Image newImageRecord = new Image();
        newImageRecord.setContentId(contentId);
        newImageRecord.setImageUrl(imageUrl);
        imageMapper.insert(newImageRecord);
        log.info("图片记录创建成功，内容ID: {}, 图片ID: {}, URL: {}", contentId, imageId, imageUrl);

        // 4. 更新操作日志进度
        operationLogService.incrementCompletedOperations(operationLogId);
        log.info("操作进度更新成功，内容ID: {}, 操作日志ID: {}", contentId, operationLogId);
    }

// 5. 添加清理临时文件的方法
    /**
     * 清理临时文件
     */
    private void cleanupTempFiles(List<String> tempFilePaths) {
        if (tempFilePaths != null) {
            for (String tempPath : tempFilePaths) {
                deleteTempFile(tempPath);
            }
        }
    }


    // ================================ 保持原有的私有方法 ================================

    /**
     * 从临时文件上传到文件服务器
     */
    private void uploadFileFromTemp(String tempFilePath, String targetPath, String contentType) throws IOException {
        HttpClient client = HttpClient.newBuilder()
                .version(HttpClient.Version.HTTP_1_1)
                .build();

        String auth = Base64.getEncoder().encodeToString((fileServerUsername + ":" + fileServerPassword).getBytes());
        String fileUrl = fileServerUrl + "/files/" + targetPath;

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(fileUrl))
                .header("Authorization", "Basic " + auth)
                .header("Content-Type", contentType)
                .PUT(HttpRequest.BodyPublishers.ofFile(Paths.get(tempFilePath)))
                .build();

        try {
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
            if (response.statusCode() < 200 || response.statusCode() >= 300) {
                throw new IOException("文件上传失败，状态码: " + response.statusCode() + ", 响应: " + response.body());
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new IOException("文件上传被中断", e);
        }
    }

    /**
     * 复制默认封面到文件服务器
     */
    private void copyDefaultCoverToServer(Long contentId) throws IOException {
        try (InputStream in = getClass().getResourceAsStream(defaultCoverPath)) {
            if (in == null) {
                throw new IOException("默认封面文件不存在: " + defaultCoverPath);
            }

            String filePath = "springboot/littleRedBook/content/" + contentId + "/cover.jpg";

            HttpClient client = HttpClient.newBuilder()
                    .version(HttpClient.Version.HTTP_1_1)
                    .build();

            String auth = Base64.getEncoder().encodeToString((fileServerUsername + ":" + fileServerPassword).getBytes());

            HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create(fileServerUrl + "/files/" + filePath))
                    .header("Authorization", "Basic " + auth)
                    .header("Content-Type", "image/jpeg")
                    .PUT(HttpRequest.BodyPublishers.ofInputStream(() -> {
                        try {
                            return getClass().getResourceAsStream(defaultCoverPath);
                        } catch (Exception e) {
                            throw new UncheckedIOException(new IOException("读取默认封面失败", e));
                        }
                    }))
                    .build();

            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

            if (response.statusCode() < 200 || response.statusCode() >= 300) {
                throw new IOException("上传默认封面失败，状态码: " + response.statusCode());
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new IOException("上传默认封面被中断", e);
        }
    }

    /**
     * 更新内容上传状态
     */
    private void updateContentUploadStatus(Long contentId, String status) {
        Content updateContent = new Content();
        updateContent.setId(contentId);
        updateContent.setUploadStatus(status);
        contentMapper.updateById(updateContent);
        log.info("内容上传状态更新，内容ID: {}, 状态: {}", contentId, status);
    }

    /**
     * 从文件服务器删除文件
     */
    private void deleteFileFromServer(String filePath) throws IOException {
        HttpClient client = HttpClient.newBuilder()
                .version(HttpClient.Version.HTTP_1_1)
                .build();

        String auth = Base64.getEncoder().encodeToString((fileServerUsername + ":" + fileServerPassword).getBytes());
        String fileUrl = fileServerUrl + "/files/" + filePath;

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(fileUrl))
                .header("Authorization", "Basic " + auth)
                .method("DELETE", HttpRequest.BodyPublishers.noBody())
                .build();

        try {
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

            if (response.statusCode() != 204 && response.statusCode() != 404) {
                // 404是可接受的，意味着文件不存在
                log.warn("删除文件返回状态码: {}, 文件: {}", response.statusCode(), filePath);
            } else {
                log.info("成功删除文件: {}", filePath);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new IOException("删除文件被中断", e);
        }
    }


    // ================================ 保持原有的工具方法 ================================

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String filePath) {
        if (filePath == null) {
            return ".jpg";
        }
        int lastDotIndex = filePath.lastIndexOf(".");
        if (lastDotIndex > 0 && lastDotIndex < filePath.length() - 1) {
            return filePath.substring(lastDotIndex);
        }
        return ".jpg"; // 默认扩展名
    }

    /**
     * 根据文件路径获取图片Content-Type
     */
    private String getImageContentType(String filePath) {
        if (filePath == null) {
            return "image/jpeg";
        }
        String lowerPath = filePath.toLowerCase();
        if (lowerPath.endsWith(".png")) {
            return "image/png";
        } else if (lowerPath.endsWith(".gif")) {
            return "image/gif";
        } else if (lowerPath.endsWith(".webp")) {
            return "image/webp";
        } else if (lowerPath.endsWith(".jpg") || lowerPath.endsWith(".jpeg")) {
            return "image/jpeg";
        } else {
            return "image/jpeg"; // 默认
        }
    }

    /**
     * 根据文件路径获取视频Content-Type
     */
    private String getVideoContentType(String filePath) {
        if (filePath == null) {
            return "video/mp4";
        }
        String lowerPath = filePath.toLowerCase();
        if (lowerPath.endsWith(".mp4")) {
            return "video/mp4";
        } else if (lowerPath.endsWith(".avi")) {
            return "video/avi";
        } else if (lowerPath.endsWith(".mov")) {
            return "video/quicktime";
        } else if (lowerPath.endsWith(".webm")) {
            return "video/webm";
        } else {
            return "video/mp4"; // 默认
        }
    }

    /**
     * 删除临时文件
     */
    private void deleteTempFile(String tempFilePath) {
        try {
            File tempFile = new File(tempFilePath);
            if (tempFile.exists()) {
                boolean deleted = tempFile.delete();
                if (deleted) {
                    log.debug("临时文件删除成功: {}", tempFilePath);
                } else {
                    log.warn("临时文件删除失败: {}", tempFilePath);
                }
            }
        } catch (Exception e) {
            log.warn("删除临时文件异常: {}", tempFilePath, e);
        }
    }

    // ================================ 保持原有的验证方法 ================================

    /**
     * 验证上传的文件是否为有效的图片格式
     */
    public void validateImageFile(org.springframework.web.multipart.MultipartFile file) {
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("请选择要上传的文件");
        }

        String contentType = file.getContentType();
        if (contentType == null || !contentType.startsWith("image/")) {
            throw new IllegalArgumentException("请上传图片格式的文件");
        }

        // 检查文件大小（限制为5MB）
        long maxSize = 5 * 1024 * 1024; // 5MB
        if (file.getSize() > maxSize) {
            throw new IllegalArgumentException("图片文件大小不能超过5MB");
        }

        // 检查文件扩展名
        String originalFilename = file.getOriginalFilename();
        if (originalFilename != null) {
            String lowerFileName = originalFilename.toLowerCase();
            if (!lowerFileName.endsWith(".jpg") &&
                    !lowerFileName.endsWith(".jpeg") &&
                    !lowerFileName.endsWith(".png") &&
                    !lowerFileName.endsWith(".gif") &&
                    !lowerFileName.endsWith(".webp")) {
                throw new IllegalArgumentException("只支持 JPG、PNG、GIF、WebP 格式的图片");
            }
        }
    }

    /**
     * 验证上传的文件是否为有效的视频格式
     */
    public void validateVideoFile(org.springframework.web.multipart.MultipartFile file) {
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("请选择要上传的文件");
        }

        String contentType = file.getContentType();
        if (contentType == null || !contentType.startsWith("video/")) {
            throw new IllegalArgumentException("请上传视频格式的文件");
        }

        // 检查文件大小（限制为100MB）
        long maxSize = 100 * 1024 * 1024; // 100MB
        if (file.getSize() > maxSize) {
            throw new IllegalArgumentException("视频文件大小不能超过100MB");
        }

        // 检查文件扩展名
        String originalFilename = file.getOriginalFilename();
        if (originalFilename != null) {
            String lowerFileName = originalFilename.toLowerCase();
            if (!lowerFileName.endsWith(".mp4") &&
                    !lowerFileName.endsWith(".avi") &&
                    !lowerFileName.endsWith(".mov") &&
                    !lowerFileName.endsWith(".webm")) {
                throw new IllegalArgumentException("只支持 MP4、AVI、MOV、WebM 格式的视频");
            }
        }
    }
}